#include "fireemblem/engine/Game.h"
using namespace fireemblem::engine;

#include "noria/Marshal.h"
#include "noria/io/File.h"
//#include "noria/net/Dns.h"
//#include "noria/window/Window.h"
#include "noria/media/sound/SoundManager.h"
using namespace noria;
using namespace noria::io;
//using namespace noria::net;
//using namespace noria::window;
using namespace noria::media::sound;

#include <iostream>
#include <vector>
#include <locale>
#include <fstream>
#include <sstream>
#include <string>
#include <memory>
#include <mbctype.h>
using namespace std;


//static inline IReflectable* Box(IReflectable* v)
//{
//	return v;
//}
//
//template<typename T>
//static inline IReflectable* Box(T v)
//{
//	static auto& marshal = AcGetMarshal();
//	return marshal.Box(v);
//}


#define EXPAND(X) X    // for MSVC10 compatibility

// compute number of (variadic) macro arguments
// from http://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1
#define PP_NARG(...) EXPAND( PP_NARG_(__VA_ARGS__, PP_RSEQ_N()) )
#define PP_NARG_(...) EXPAND( PP_ARG_N(__VA_ARGS__) )
#define PP_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define PP_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0


//auto& marshal = AcGetMarshal();

#define ARRAY(...) &vector<IReflectable*>{ __VA_ARGS__ }[0]
#define BOX(v) &IReflectablePtr(AcMarshal.Box(v))
//#define BOX(v) &IReflectablePtr(Activator::GetMarshal().Box(v))
//#define BOX(v) &IReflectablePtr(Box(v))

#define R_1(_1) 				ARRAY( BOX(_1) )
#define R_2(_1, _2) 			ARRAY( BOX(_1), BOX(_2) )
#define R_3(_1, _2, _3) 		ARRAY( BOX(_1), BOX(_2), BOX(_3) )
#define R_4(_1, _2, _3, _4) 	ARRAY( BOX(_1), BOX(_2), BOX(_3), BOX(_4) )
#define R_5(_1, _2, _3, _4, _5)	ARRAY( BOX(_1), BOX(_2), BOX(_3), BOX(_4), BOX(_5) )

#define R_6(_1, _2, _3, _4, _5, _6)						ARRAY( BOX(_1), BOX(_2), BOX(_3), BOX(_4), BOX(_5), BOX(_6) )
#define R_7(_1, _2, _3, _4, _5, _6, _7)					ARRAY( BOX(_1), BOX(_2), BOX(_3), BOX(_4), BOX(_5), BOX(_6), BOX(_7) )

// macro selection by number of arguments
#define R_(N) R_##N
#define R_EVAL(N) R_(N)
#define R(...) EXPAND( R_EVAL(EXPAND( PP_NARG(__VA_ARGS__) ))(__VA_ARGS__) )


int main2()
{
	try
	{
		auto s = S("hello");
		auto index = s->IndexOf('e');

		// sound manager
		auto& sm = AcGetSoundManager();

		// file
		auto fs = AcCreateFile();
		fs->OpenWrite("mc.txt");
		//fs << "some sample text";
		//fs << "some addiontal sample text" << endl;
		fs->Close();




		//IReflectablePtr a = marshal.Box(777);
		//IReflectablePtr b = marshal.Box(false);
		//IReflectablePtr c = marshal.Box("another song.acc");
		//vector<IReflectable*> args{ c.Get() };
		//IReflectable* args2[]{ a.Get(), b.Get()};

		//IReflectable** pp = &args[0];
		//IReflectable &ref = *pp[0];

		//char *cc;
		//marshal.Unbox(ref, &cc);

//#define R(a) &vector<IReflectable*>{ &IReflectablePtr(marshal.Box(a)) }[0]
//#define R(a,b) &vector<IReflectable*>{ &IReflectablePtr(marshal.Box(a)), &IReflectablePtr(marshal.Box(b)) }[0]

		auto raw_string = R"(some text)";
		auto raw_stringL = LR"(some text)";
		sm.PlayMusic("heroes.acc");
		sm.Invoke("PlayMusic", R("what.wave"));
		sm.Invoke("PlayMusic", R(R"(poker face.acc)", 77));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));
		sm.Invoke("PlayMusic", R("another song.acc", 77, false, 1.0, ""));

		cout << "press any key to exit..." << endl;
		getchar();

		sm = AcGetSoundManager();
		sm.Stop();


		// The following code makes memory leak explicitly
		//Activator::CreateInstance("libnmm", "noria.media.sound.SoundManager");
	}
	catch (const exception &e)
	{
		cerr << "error: " << e.what() << endl;
	}

	return 0;
}

int main()
{
	AcCreateGame()->Run();
	return 0;
}